package com.smart.car.member.exception;

import com.smart.car.common.res.bean.ResponseResult;
import com.smart.car.common.res.constant.Constants;
import com.smart.car.common.res.exception.JsonException;
import com.smart.car.common.res.exception.PageException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.ModelAndView;

import java.util.HashMap;
import java.util.Map;

/**
 * TODO 控制层的统一异常处理
 * 包括了两种方式的处理：
 * 第一种对常见API形式的接口进行异常处理，统一封装返回格式。
 * 第二种是对模板页面请求的异常处理，统一处理错误页面。(需要在resources下增加一个error.html)
 * @author zoutao.blog.csdn.net
 * @date 2021/3/12
 */
@Slf4j
//@RestControllerAdvice(basePackages = "com.smart.car.member.controller")
public class ExceptionControllerAdvice {

    /**
     * 统一 json 异常处理
     * @param exception JsonException
     * @return 统一返回 json 格式
     */
    @ExceptionHandler(value = JsonException.class)
    @ResponseBody
    public ResponseResult jsonErrorHandler(JsonException exception) {
        log.error("【JsonException】:{}", exception.getMessage());
        return ResponseResult.fail(exception);
    }

    /**
     * 统一 页面 异常处理
     * @param exception PageException
     * @return 统一跳转到异常页面
     */
    @ExceptionHandler(value = PageException.class)
    public ModelAndView pageErrorHandler(PageException exception) {
        log.error("【DemoPageException】:{}", exception.getMessage());
        ModelAndView view = new ModelAndView();
        view.addObject("message", exception.getMessage());
        view.setViewName("error");
        return view;
    }

    //参数校验异常处理
    @ResponseBody
    @ExceptionHandler(value= MethodArgumentNotValidException.class)
    public ResponseResult handleValidException(MethodArgumentNotValidException e) {
        log.error("数据校验出现问题{}，异常类型：{}", e.getMessage(), e.getClass());
        // 从异常对象中拿到ObjectError对象
        BindingResult bindingResult = e.getBindingResult();
        Map<String, String> errorMap = new HashMap<>();
        bindingResult.getFieldErrors().forEach((fieldError)->{
            // 提取错误提示信息
            errorMap.put(fieldError.getField(), fieldError.getDefaultMessage());
        });
        ResponseResult result = new ResponseResult();
        result.setCode(Constants.BAD_REQUEST);
        result.setMsg(Constants.VALID_EXCEPTION_MSG);
        result.setData(errorMap);
        return result;
    }

    //全局方法异常处理
    @ExceptionHandler(value=Throwable.class)
    public ResponseResult handleException(Throwable throwable) {
        log.error("未知异常：{}，异常类型：{}", throwable.getMessage(), throwable.getClass());
        ResponseResult result = new ResponseResult();
        result.setCode(Constants.UNKNOWN_EXCEPTION_CODE);
        result.setMsg(Constants.UNKNOWN_EXCEPTION_MSG);
        return result;
    }

}
